# 连接数据库sqlite
import sqlite3
from datetime import datetime
import click
from flask import current_app,g

'''
g是一个特殊对象，每个请求都是唯一的。
    它用于存储在请求期间可能被多个函数访问的数据。
    所以get_db()重复被调用，不会创建新的连接
detect_types=sqlite3.PARSE_DECLTYPES
    让 SQLite 根据字段声明类型，自动将存储的数据转换为 Python 对应类型
    与 datetime 类型结合使用，确保数据库中的时间戳能正确转换为 Python 
    的 datetime 对象，便于后续处理
'''

'''
1.定义数据库操作
'''
def get_db():
    if 'db' not in g:
        g.db = sqlite3.connect(
            current_app.config['DATABASE'],
                detect_types=sqlite3.PARSE_DECLTYPES
        )
        #sqlite3.Row告诉连接返回类似于字典的行。允许通过名称访问列。
        g.db.row_factory = sqlite3.Row
    return g.db

# e=None 使flask调用函数时可以传递异常对象
def close_db(e=None):
    # 获取连接
    db = g.pop('db',None)
    if db is not None:
        db.close()

'''
2.打开数据库文件
'''
def init_db():
    db = get_db()
    # with自动关闭文件 open_resource默认打开相对于flaskr的文件
    with current_app.open_resource('./user_table.sql') as f:
        db.executescript(f.read().decode('utf-8'))

'''
3.定义命令行命令
'''
@click.command('init-db')
def init_db_command():
    init_db()
    click.echo('Initialized the database.') #click.echo() 命令行输出命令

'''
4.时间戳转为datetime
'''
sqlite3.register_converter(
    # v.decode()：将 bytes 转换为 str（默认使用 UTF-8 编码）。
    # datetime.fromisoformat()：将符合 ISO 8601 格式的字符串转换为 datetime 对象。
    '''
    匿名函数 lambda 参数: 返回值
    '''
    "timestamp", lambda v: datetime.fromisoformat(v.decode())
)

'''
5.注册应用程序
'''
# 将数据库操作与应用程序绑定
def init_app(app):
    app.teardown_appcontext(close_db) # 自动关闭数据库连接
    app.cli.add_command(init_db_command) # 向 Flask 命令行接口（CLI）添加自定义命令